#include <memory>
#include <iostream>

#include <odb/database.hxx>
#include <odb/mysql/database.hxx>
#include "student.hxx"
#include "student-odb.hxx"
#include <gflags/gflags.h>

DEFINE_string(host, "127.0.0.1", "这是Mysql服务器地址");
DEFINE_int32(port, 0, "这是Mysql服务器端口");
DEFINE_string(db, "TestDB", "数据库默认库名称");
DEFINE_string(user, "root", "这是Mysql用户名");
DEFINE_string(pswd, "123456", "这是Mysql密码");
DEFINE_string(cset, "utf8", "这是Mysql客户端字符集");
DEFINE_int32(max_pool, 3, "这是Mysql连接池最大连接数量");


void insert_classes(odb::mysql::database& db)
{
    try
    {
        // 3. 获取事务操作对象，开启事务
        odb::transaction trans(db.begin());
        Classes C1("一年级一班");
        Classes C2("一年级二班");
        db.persist(C1);
        db.persist(C2);
        // 5. 提交事务
        trans.commit();
    }
    catch(const std::exception& e)
    {
        std::cerr << "插入班级数据出错: " << e.what() << std::endl;
    }
    
}

void insert_student(odb::mysql::database& db)
{
    try
    {
        // 获取事务操作对象，开启事务
        odb::transaction trans(db.begin());
        Student S1(1, "张三", 18, 1);
        Student S2(2, "李四", 19, 1);
        Student S3(3, "王五", 18, 1);
        Student S4(4, "赵六", 15, 2);
        Student S5(5, "刘七", 18, 2);
        Student S6(6, "孙八", 23, 2);
        db.persist(S1);
        db.persist(S2);
        db.persist(S3);
        db.persist(S4);
        db.persist(S5);
        db.persist(S6);

        // 提交事务
        trans.commit();
    }
    catch(const std::exception& e)
    {
        std::cerr << "插入学生数据出错: " << e.what() << std::endl;
    }
}

void update_student(odb::mysql::database& db, Student &stu)
{
    try
    {
        // 获取事务操作对象，开启事务
        odb::transaction trans(db.begin());
        db.update(stu);

        // 提交事务
        trans.commit();
    }
    catch(const std::exception& e)
    {
        std::cerr << "更新学生数据出错: " << e.what() << std::endl;
    }
}

Student select_student(odb::mysql::database& db)
{
    Student res;
    try
    {
        // 获取事务操作对象，开启事务
        odb::transaction trans(db.begin());
        typedef odb::query<Student> query;
        typedef odb::result<Student> result;
        result r(db.query<Student>(query::name == "张三"));
        if(r.size() != 1)
        {
            std::cout << "数据量不对! \n";
            return Student();
        }
        res = *r.begin();

        // 提交事务
        trans.commit();
    }
    catch(const std::exception& e)
    {
        std::cerr << "查询学生数据出错: " << e.what() << std::endl;
    }
    return res;
}

// void remove_student(odb::mysql::database& db)
// {
//     try
//     {
//         // 获取事务操作对象，开启事务
//         odb::transaction trans(db.begin());
//         typedef odb::query<Student> query;
//         db.erase_query<Student>(query::name == "孙八");

//         // 提交事务
//         trans.commit();
//     }
//     catch(const std::exception& e)
//     {
//         std::cerr << "删除学生数据出错: " << e.what() << std::endl;
//     }    
// }

void remove_student(odb::mysql::database& db)
{
    try
    {
        // 获取事务操作对象，开启事务
        odb::transaction trans(db.begin());
        typedef odb::query<Student> query;
        db.erase_query<Student>(query::classes_id == 2);

        // 提交事务
        trans.commit();
    }
    catch(const std::exception& e)
    {
        std::cerr << "删除学生数据出错: " << e.what() << std::endl;
    }    
}

void classes_student(odb::mysql::database& db)
{
    try
    {
        // 获取事务操作对象，开启事务
        odb::transaction trans(db.begin());
        typedef odb::query<struct classes_student> query;
        typedef odb::result<struct classes_student> result;
        result r(db.query<struct classes_student>(query::classes::name == "一年级一班"));

        if(r.size() == 0)
        {
            std::cout << "数据量不对! \n";
            return ;  
        }

        for(auto it = r.begin(); it != r.end(); ++it)
        {
            std::cout << it->id << std::endl;
            std::cout << it->sn << std::endl;
            std::cout << it->name << std::endl;
            std::cout << *it->age << std::endl;
            std::cout << it->classes_name << std::endl;
            std::cout <<"-------------------------\n";
        }

        // 提交事务
        trans.commit();
    }
    catch(const std::exception& e)
    {
        std::cerr << "查询学生数据出错: " << e.what() << std::endl;
    }
}


// void all_student(odb::mysql::database& db)
// {
//     try
//     {
//         // 获取事务操作对象，开启事务
//         odb::transaction trans(db.begin());
//         typedef odb::query<struct all_name> query;
//         typedef odb::result<struct all_name> result;
//         result r(db.query<struct all_name>());

//         if(r.size() == 0)
//         {
//             std::cout << "数据量不对! \n";
//             return ;  
//         }

//         for(auto it = r.begin(); it != r.end(); ++it)
//         {
//             std::cout << it->name << std::endl;
//         }

//         // 提交事务
//         trans.commit();
//     }
//     catch(const std::exception& e)
//     {
//         std::cerr << "查询所有学生姓名数据出错: " << e.what() << std::endl;
//     }
// }

void all_student(odb::mysql::database& db)
{
    try
    {
        // 获取事务操作对象，开启事务
        odb::transaction trans(db.begin());
        typedef odb::query<Student> query;
        typedef odb::result<struct all_name> result;
        result r(db.query<struct all_name>(query::id == 1));

        if(r.size() == 0)
        {
            std::cout << "数据量不对! \n";
            return ;  
        }

        for(auto it = r.begin(); it != r.end(); ++it)
        {
            std::cout << it->name << std::endl;
        }

        // 提交事务
        trans.commit();
    }
    catch(const std::exception& e)
    {
        std::cerr << "查询所有学生姓名数据出错: " << e.what() << std::endl;
    }
}



int main(int argc, char *argv[])
{
    // 解析命令行参数
    google::ParseCommandLineFlags(&argc, &argv, true); 

    // 1. 构造连接池工厂配置对象
    std::unique_ptr<odb::mysql::connection_pool_factory> cpf(
        new odb::mysql::connection_pool_factory(FLAGS_max_pool, 0));

    // 2. 构造数据库操作对象
    odb::mysql::database db(
        FLAGS_user, FLAGS_pswd, FLAGS_db, 
        FLAGS_host, FLAGS_port, "", FLAGS_cset,
        0, std::move(cpf));

    
    // 4. 数据操作
    // insert_classes(db);
    // insert_student(db);
    
    // auto stu = select_student(db);
    // std::cout << stu.sn() << std::endl;
    // std::cout << stu.name() << std::endl;
    // if(stu.age()) std::cout << *stu.age() << std::endl;
    // std::cout << stu.classes_id() << std::endl;
    // stu.age(15);
    // update_student(db, stu);

    // remove_student(db);
    // classes_student(db);
    all_student(db);

    return 0;
}
